//
//  GGRoute.m
//  qqqqqq
//
//  Created by iOSer on 2017/3/3.
//  Copyright © 2017年 iOSer. All rights reserved.
//

#import "GGRoute.h"
#import "GGRouteMatcher.h"
#import "GGRouteHandler.h"
#import "NSError+GGRouteError.h"
static NSString *routeConfigName = @"GGRouteConfig";
@interface GGRoute()
@property(nonatomic,strong) NSMutableDictionary *routeMatchers;
@property(nonatomic,strong) NSMutableDictionary *routeHandles;
@property(nonatomic,strong) NSMutableDictionary *routeblocks;
@end
@implementation GGRoute

static GGRoute *  ggRoute = nil;
+(GGRoute *)shareGGRouterInstance{
    static dispatch_once_t once;
    dispatch_once(&once, ^(){
        ggRoute = [[GGRoute alloc] init];
    });
    return ggRoute;
}

-(instancetype)init{
    if (self = [super init]) {
        _routeblocks = [NSMutableDictionary dictionary];
        _routeHandles = [NSMutableDictionary dictionary];
        _routeMatchers = [NSMutableDictionary dictionary];
        
    }
    return self;
}

-(void)registerHandlers{
    NSString *plistPath = [[NSBundle mainBundle] pathForResource:routeConfigName ofType:@"plist"];
    NSMutableDictionary *data = [[NSMutableDictionary alloc] initWithContentsOfFile:plistPath];
    NSArray *array = data[@"RegisterModule"];
    for (NSDictionary *dic in array) {
        NSString *HandleClassName = dic[@"HandlerClassName"];
        NSString *routeStr = dic[@"RouteStr"];
        [self registerHandler:[NSClassFromString(HandleClassName) new] forRoute:routeStr];
    }
}
-(id)objectForKeyedSubscript:(NSString *)key{
    NSString * route = (NSString *)key;
    id obj = nil;
    if ([route isKindOfClass:[NSString class]] && [route length]) {
        obj = self.routeHandles[route];
        if (obj == nil) {
            obj = self.routeblocks[route];
        }
    }
    return obj;
}
-(void)registerBlock:(GGRouteRequest *(^)(GGRouteRequest *))routeHandlerBlock forRoute:(NSString *)route{
    if (routeHandlerBlock && [route length]) {
        [self.routeMatchers setObject:[GGRouteMatcher matcherWithRouteExpression:route] forKey:route];
        [self.routeHandles removeObjectForKey:route];
        self.routeblocks[route] = routeHandlerBlock;
    }
}

-(void)registerHandler:(GGRouteHandler *)handler forRoute:(NSString *)route{
    if (handler && [route length]) {
        //
        [self.routeMatchers setObject:[GGRouteMatcher matcherWithRouteExpression:route] forKey:route];
        [self.routeblocks removeObjectForKey:route];
        self.routeHandles[route] = handler;
    }
}

-(BOOL)handleURL:(NSURL *)URL primitiveParameters:(NSDictionary *)primitiveParameters isJumpMothod:(JumpMethod)Method isShowNav:(BOOL)isShowNav NAVTitle:(NSString *)navTitle isNavAnimation:(BOOL)isNavAnimation targetCallBack:(void (^)(NSError *error, id responseObject))targetCallBack withCompletionBlock:(void (^)(BOOL handled, NSError *error))completionBlock{
    if (!URL) {
        return NO;
    }
    NSError *error;
    GGRouteRequest *request;
    __block BOOL isHandled = NO;
    for (NSString *route in self.routeMatchers.allKeys) {
        
        GGRouteMatcher *matcher = [self.routeMatchers objectForKey:route];
        request = [matcher createRequestWithURL:URL primitiveParameters:primitiveParameters isJumpMethod:Method isShowNav:isShowNav NAVTitle:navTitle isNavAnimation:isNavAnimation targetCallBack:targetCallBack];
        if (request) {
            isHandled = [self handleRouteExpression:route withRequest:request error:&error];
            break;
        }
    }
    if (!request) {
        error = [NSError GGNotFoundError];
    }
    [self completeRouteWithSuccess:isHandled error:error completionHandler:completionBlock];
    
    return isHandled;
}
//根据request进行handler的生命周期函数调用或者是block回调
-(BOOL)handleRouteExpression:(NSString *)routeExpression withRequest:(GGRouteRequest *)request error:(NSError *__autoreleasing *)error{
    id handler = self[routeExpression];
    //self.routeHandles和self.routeblocks拿到route对应的回调block或者是handler实例
    if ([handler isKindOfClass:NSClassFromString(@"NSBlock")]) {
        GGRouteRequest *(^block)(GGRouteRequest *) = handler;
        //调用回调的block
        GGRouteRequest *backRequest = block(request);
        //判断block里面是否消费了此request，如果没有而目标设置了目标回调targetCallBack，那么在此进行默认回调
        if (backRequest.isConsumed == NO) {
            if (backRequest.targetCallBack) {
                dispatch_async(dispatch_get_main_queue(), ^{
                    backRequest.targetCallBack(nil,nil);
                });
            }
        }
        return YES;
    }
    else if ([handler isKindOfClass:[GGRouteHandler class]]){
        //拿到url对应的handler对象后，先调用handler的shouldHandleWithRequest方法，如果返回YES，则调用进行转场的transitionWithRequest方法
        GGRouteHandler *rHandler = (GGRouteHandler *)handler;
        if (![rHandler shouldHandleWithRequest:request]) {
            return NO;
        }
        return [rHandler handleRequest:request error:error];
    }
    return YES;
}
- (void)completeRouteWithSuccess:(BOOL)handled error:(NSError *)error completionHandler:(void(^)(BOOL handled, NSError *error))completionHandler {
    if (completionHandler) {
        dispatch_async(dispatch_get_main_queue(), ^{
            completionHandler(handled, error);
        });
    }
}
@end
